package com.example.photographWatermark.util

import android.content.res.Resources
import android.graphics.*
import android.media.ExifInterface
import android.os.Build
import android.text.StaticLayout
import android.text.TextPaint
import android.util.Log
import androidx.annotation.RequiresApi
import com.example.photographWatermark.camera2.CameraBean
import com.example.photographWatermark.camera2.ImageCallback
import okio.buffer
import okio.sink
import java.io.ByteArrayOutputStream
import java.io.IOException
import kotlin.concurrent.thread


/**
 *
 * author : ChenSen
 * data : 2018/3/16
 * desc:
 */
object BitmapUtils {

    fun toByteArray(bitmap: Bitmap): ByteArray {
        var os = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)
        return os.toByteArray()
    }

    fun mirror(rawBitmap: Bitmap): Bitmap {
        var matrix = Matrix()
        matrix.postScale(-1f, 1f)
        return Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.width, rawBitmap.height, matrix, true)
    }

    fun rotate(rawBitmap: Bitmap, degree: Float): Bitmap {
        var matrix = Matrix()
        matrix.postRotate(degree)
        return Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.width, rawBitmap.height, matrix, true)
    }

    fun decodeBitmap(bitmap: Bitmap, reqWidth: Int, reqHeight: Int): Bitmap {
        var options = BitmapFactory.Options()
        options.inJustDecodeBounds = true

        var bos = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos)
        BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size(), options)

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size(), options)
    }

    fun decodeBitmapFromFile(path: String, reqWidth: Int, reqHeight: Int): Bitmap {
        var options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(path, options)

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeFile(path, options)
    }

    fun decodeBitmapFromResource(res: Resources, resId: Int, reqWidth: Int, reqHeight: Int): Bitmap {
        var options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, options)

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeResource(res, resId, options)
    }

    private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
        val rawWidth = options.outWidth
        val rawHeight = options.outHeight
        var inSampleSize = 1

        if (rawWidth > reqWidth || rawHeight > reqHeight) {
            val halfWidth = rawWidth / 2
            val halfHeight = rawHeight / 2

            while ((halfWidth / inSampleSize) > reqWidth && (halfHeight / inSampleSize) > reqHeight) {
                inSampleSize *= 2  //设置inSampleSize为2的幂是因为解码器最终还是会对非2的幂的数进行向下处理，获取到最靠近2的幂的数
            }
        }
        return inSampleSize
    }

    fun savePic(data: ByteArray?, isMirror: Boolean = false, callback: ImageCallback, bean:
    CameraBean, locationBitmap: Bitmap, userBitmap: Bitmap) {
        thread {
            try {
                val temp = System.currentTimeMillis()
                val picFile = FileUtil.createCameraFile("camera2")
                if (picFile != null && data != null) {

                    val rawBitmap: Bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
//                    val resultBitmap = if (isMirror) mirror(rawBitmap) else rawBitmap
//                    val angle = readPictureDegree(picFile.absolutePath)
                    val rawBitmap1 = matrixBitmap(rawBitmap, 90)
                    drawText(rawBitmap1, bean, 30f, Color.WHITE, locationBitmap, userBitmap)
                    picFile.sink().buffer().write(toByteArray(rawBitmap1)).close()
                    Log.d("------", "图片已保存! 耗时：${System.currentTimeMillis() - temp}    路径：  ${picFile
                            .absolutePath}")
                    callback.onSuccess(picFile.absolutePath)

                }
            } catch (e: Exception) {
                e.printStackTrace()
//                onFailed("${e.message}")
            }
        }
    }

    private fun drawText(bitmap: Bitmap, bean: CameraBean, size: Float, color: Int, locationBitmap: Bitmap, userBitmap: Bitmap) {

        drawRectBg(bitmap)
        drawTextToLeftTop(bitmap, bean.mDate, size, color, 40, bitmap.height * 3 / 4 - 30)
        drawTextToLeftTop(bitmap, bean.mUserName, size, color, 90, bitmap.height *
                3 / 4 + 30)

        drawIcon(userBitmap, bitmap, 40, bitmap.height *
                3 / 4 + 25, 0.3f, 0.3f)
        drawTextToLeftTop(bitmap, bean.mAddress, size, color, 90, bitmap.height *
                3 / 4 + 100)
        drawIcon(locationBitmap, bitmap, 40, bitmap.height *
                3 / 4 + 95, 0.4f, 0.4f)

    }

    private fun drawIcon(drawable: Bitmap, bitmap: Bitmap,
                         paddingLeft: Int, paddingTop: Int, sx: Float, sy: Float) {
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.isDither = true
        paint.isFilterBitmap = true
        val canvas = Canvas(bitmap)
        val matrix = Matrix()
        matrix.postScale(sx, sy)
        matrix.postTranslate(paddingLeft.toFloat(), paddingTop.toFloat())
        canvas.drawBitmap(drawable, matrix, paint)
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun drawTextToLeftTop(bitmap: Bitmap, text: String, size: Float, color: Int,
                                  paddingLeft: Int, paddingTop: Int) {
//        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
//        paint.color = color
//        paint.textSize = size
//        paint.getTextBounds(text, 0, text.length, Rect())
//        paint.isDither = true
//        paint.isFilterBitmap = true
        val canvas = Canvas(bitmap)
        val tp = TextPaint()
        tp.color = color
        tp.textSize = size
        tp.getTextBounds(text, 0, text.length, Rect())
//        val staticLayout = StaticLayout(text,tp,canvas.width,Layout.Alignment.ALIGN_NORMAL,1.0f,1.0f,false);
        val staticLayout = StaticLayout.Builder.obtain(text, 0, text.length, tp, canvas.width).build()
        canvas.translate(paddingLeft.toFloat(), paddingTop.toFloat());
        staticLayout.draw(canvas)
    }


    private fun drawRectBg(bitmap: Bitmap) {
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.color = Color.parseColor("#80000000")
//        paint.textSize = size
        val bounds = RectF(20f, bitmap.height * 3 / 4 - 60f, bitmap.width - 20f, bitmap.height * 2
                / 3 +
                300f)
        var bitmapConfig = bitmap.config;
        paint.isDither = true
        paint.isFilterBitmap = true
//        paint.strokeCap = Paint.Cap.ROUND
//        paint.shader = Shader().
        val canvas = Canvas(bitmap)
        canvas.drawRoundRect(bounds, 16f, 16f, paint)
//        canvas.drawRect(bounds, paint)
    }


    private fun matrixBitmap(bitmap: Bitmap, angle: Int): Bitmap {
        val matrix = Matrix()
        matrix.postRotate(angle.toFloat())
//        bitmap.recycle()
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }

    //读取数据的旋转方向
    private fun readPictureDegree(path: String): Int {
        var degree = 0
        try {
            val exifInterface = ExifInterface(path)
            val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL)
            degree = when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> 90
                ExifInterface.ORIENTATION_ROTATE_180 -> 180
                ExifInterface.ORIENTATION_ROTATE_270 -> 270
                else -> 0
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return degree
    }
}